import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue';
import {
  baseProps,
  makeArrayProp,
  makeBooleanProp,
  makeStringProp,
} from 'wot-design-uni/components/common/props';
import { getType, isArray, isObj } from 'wot-design-uni/components/common/util';

/** 列项 */
export type ColumnItem = {
  /** 键 */
  [key: string]: any;
  /** 图标 */
  icon?: string;
  /** 颜色 */
  color?: string;
  /** 值 */
  value?: string | number | boolean;
  /** 标签 */
  label?: string;
  /** 禁用 */
  disabled?: boolean;
};

export const pickerViewProps = {
  ...baseProps,
  /** 加载状态 */
  loading: makeBooleanProp(false),
  /** 加载的颜色，只能使用十六进制的色值写法，且不能使用缩写 */
  loadingColor: makeStringProp('#4D80F0'),
  /** 选项对象中，value对应的 key */
  valueKey: makeStringProp('value'),
  /** 选项对象中，展示的文本对应的 key */
  labelKey: makeStringProp('label'),
  /** 是否在手指松开时立即触发 change 事件 */
  immediateChange: makeBooleanProp(false),
  /** 是否多选 */
  multipleSelect: makeBooleanProp(false),
  /** 反向选择 */
  reverseSelect: makeBooleanProp(true),
  /** 选中项(多选类型为数组) */
  modelValue: {
    type: [String, Number, Array] as PropType<string | number | Array<number | string>>,
    default: '',
    required: true,
  },
  /** 选择器数据，可以为字符串数组，也可以为对象数组 */
  columns: makeArrayProp<string | number | ColumnItem>(),
};

export type PickerViewExpose = {
  getSelects: () => Record<string, any> | Record<string, any>[];
  getValues: () => string | number | (string | number)[];
  getColumnsData: () => Record<string, string>[];
  getLabels: () => string[];
  resetColumns: (columns: (string | number | ColumnItem)[]) => void;
};

export type PickerViewProps = ExtractPropTypes<typeof pickerViewProps>;

export type PickerViewInstance = ComponentPublicInstance<PickerViewProps, PickerViewExpose>;

/**
 * 格式化传入的列数据
 * 列数据统一格式化为数组
 * @param array 列数据
 * @param valueKey
 * @param labelKey
 * @returns
 */
export function formatArray(
  array: Array<string | number | ColumnItem>,
  valueKey: string,
  labelKey: string,
): ColumnItem[] {
  const tempArray: Array<string | number | ColumnItem> = isArray(array) ? array : [array];
  // 判断数组第一层的数据类型，如果存在多种类型，则抛错
  const firstLevelTypeList = new Set(array.map(getType));
  /**
   * 存在三种类型的合法数据
   * 1.数组是一维元素，所有元素都是原始值
   * 2.数组是一维元素，所有元素都是object
   * 3.数组是二维元素，二维元素可以是任意内容
   */
  if (firstLevelTypeList.size !== 1 && firstLevelTypeList.has('object')) {
    // 原始值和引用类型不用混用
    throw Error('The columns are correct');
  }
  // 转化为二维数组后需要将每一项包装成ColumnItem
  const result: Array<ColumnItem> = tempArray.map((row) => {
    // 非对象类型直接将值作为label和value
    if (!isObj(row)) {
      return {
        [valueKey]: row,
        [labelKey]: row,
      };
    }
    /**
     * 针对已经是object的，修补成{valueKey,labelKey}
     * 如果没有labelKey，用valueKey代替
     * 如果没有valueKey，用labelKey代替
     * valueKey,labelKey都没有，直接抛错
     */
    if (
      !Object.prototype.hasOwnProperty.call(row, valueKey) &&
      !Object.prototype.hasOwnProperty.call(row, labelKey)
    ) {
      throw Error("Can't find valueKey and labelKey in columns");
    }
    if (!Object.prototype.hasOwnProperty.call(row, labelKey)) {
      row[labelKey] = row[valueKey];
    }
    if (!Object.prototype.hasOwnProperty.call(row, valueKey)) {
      row[valueKey] = row[labelKey];
    }
    return row;
  });

  return result;
}
